let Cc = Components.classes;
let Ci = Components.interfaces;
let Cu = Components.utils;
let Cr = Components.results;

Cu.import("resource://gre/modules/XPCOMUtils.jsm");

if (typeof sbPlayerControls == "undefined") {
  var sbPlayerControls = {};
}

sbPlayerControls = {

  mm: null,             // MediaCoreManager

  // Dataremotes
  isPlaying: null,      // Is the player playing or stopped?
  fpPlaying: null,      // Are we playing and not paused?
  fpPaused: null,       // Are we playing but paused?
  fpBuffer: null,       // Are we buffering?
  fpVolume: null,       // Current volume level
  fpVolumeLast: null,   // Last known volume (before mute)

  onLoad: function() {
    this.mm = Cc["@songbirdnest.com/Songbird/Mediacore/Manager;1"]
                .getService(Ci.sbIMediacoreManager);

    // Load a new dataremote that covers actual playing/stoping
    this.isPlaying = SB_NewDataRemote("faceplate.isPlaying", null);
    this.isPlaying.boolValue = false;

    // Observe these so we update the isPlaying data remote
    this.fpPlaying = SB_NewDataRemote("faceplate.playing", null);
    this.fpPaused = SB_NewDataRemote("faceplate.paused", null);
    this.fpBuffer = SB_NewDataRemote("faceplate.buffering", null);
    this.fpPlaying.bindObserver(this, true);
    this.fpPaused.bindObserver(this, true);
    this.fpBuffer.bindObserver(this, true);

    this.updateState();
  },

  onUnLoad: function() {
    window.removeEventListener("load",
                               function(e) { sbPlayerControls.onLoad(); },
                               false);
    window.removeEventListener("unload",
                               function(e) { sbPlayerControls.onUnLoad(); },
                               false);

    this.fpPlaying.unbind();
    this.fpPaused.unbind();
    this.fpBuffer.unbind();
    this.fpPlaying = null;
    this.fpPaused = null;
    this.fpBuffer = null;
    this.isPlaying = null;
    this.mm = null;
  },


  updateState: function(aDataRemote) {
    // Update the isPlaying if any of the playing/paused/buffering changed.
    var oldValue = this.isPlaying.boolValue;
    var newValue = (this.fpPlaying.boolValue == true ||
                    this.fpPaused.boolValue == true ||
                    this.fpBuffer.boolValue == true);

    // Only update the UI if there were changes, dataremotes take care of most
    // of them
    if (oldValue == newValue) return; // no changes so abort
    this.isPlaying.boolValue = newValue;
  },


  /**
   * Command functions (play,stop, etc)
   */

  doPlay: function() {
    if (!this.mm) return;

    // If we are already playing something just pause/unpause playback
    var status = this.mm.status;
    if (status.state == Ci.sbIMediacoreStatus.STATUS_PAUSED) {
      this.mm.playbackControl.play();
    } else if(status.state == Ci.sbIMediacoreStatus.STATUS_PLAYING ||
              status.state == Ci.sbIMediacoreStatus.STATUS_BUFFERING) {
      this.mm.playbackControl.pause();
    } else {
      var event = document.createEvent("Events");
      event.initEvent("Play", true, true);
      var notHandled = document.dispatchEvent(event);
      if (notHandled) {
        // If we have no context, initiate playback
        // via the root application controller
        var app = Cc["@songbirdnest.com/Songbird/ApplicationController;1"]
                    .getService(Ci.sbIApplicationController);
        app.playDefault();
      }
    }
  },

  doStop: function() {
    if (!this.mm) return;

    this.mm.playbackControl.stop();
  },

  doPrev: function() {
    if (!this.mm) return;

    this.mm.sequencer.previous();
  },

  doNext: function() {
    if (!this.mm) return;

    this.mm.sequencer.next();
  },

  toggleRepeat: function() {
    if (!this.mm) return;

    this.mm.sequencer.repeatMode = ((this.mm.sequencer.repeatMode + 1) % 3);
  },

  toggleShuffle: function() {
    if (!this.mm) return;
    if (this.mm.sequencer.mode == this.mm.sequencer.MODE_SHUFFLE) {
      this.mm.sequencer.mode = this.mm.sequencer.MODE_FORWARD;
    }
    else {
      this.mm.sequencer.mode = this.mm.sequencer.MODE_SHUFFLE;
    }
  },

  toggleVolume: function() {
    if (!this.mm) return;
    if (!this.mm.volumeControl.mute) {
      this.fpVolumeLast.stringValue = this.fpVolume.stringValue;
      this.fpVolume.stringValue = "0.00";
    }
    else {
      this.fpVolume.stringValue = this.fpVolumeLast.stringValue;
    }
    this.mm.volumeControl.mute = !this.mm.volumeControl.mute;
  },

  /**
   * Implementation functions
   */

  // nsIObserver
  // General observer for things like dataremotes
  observe: function(aSubject, aTopic, aData) {
    // if (aSubject instanceof Ci.nsIPrefBranch)
    this.updateState(aTopic);
  }
};

window.addEventListener("load",
                        function(e) { sbPlayerControls.onLoad(e); },
                        false);
window.addEventListener("unload",
                        function(e) { sbPlayerControls.onUnLoad(e); },
                        false);
